package com.modules.api.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.response.ResponseVO;
import com.common.utils.AliyunUtils;
import com.common.utils.R;
import com.common.utils.TokenGenerator;
import com.modules.api.entity.AppUserDTO;
import com.modules.api.service.IAppService;
import com.modules.content.VO.ContentsVO;
import com.modules.content.entity.Contents;
import com.modules.content.service.IContentsService;
import com.modules.contentImages.entity.ContentImages;
import com.modules.contentImages.service.IContentImagesService;
import com.modules.system.entity.UserCode;
import com.modules.system.service.IUserCodeService;
import com.modules.user.entity.UserEntity;
import com.modules.user.service.IUserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("appService")
public class AppServiceImpl implements IAppService {

	@Autowired
	private IUserService userService;
	@Autowired
	private IUserCodeService userCodeService;
	@Autowired
	private AliyunUtils aliyunUtils;
	@Autowired
	private IContentsService contentsService;
	@Autowired
	private IContentImagesService contentImagesService;

	@Override
	public R smsSend2(Map<String, Object> param) {
		Date nowDate = new Date();
		String userName = (String) param.get("phoneNumber");

		// 查数据是否已有该用户的验证码数据，首先判断上一次验证码是否有超过五分钟并防刷，然后判断做新增还是修改
		UserCode oldUserCode = userCodeService.getOne(new QueryWrapper<UserCode>().lambda()
				.eq(UserCode::getPhone, userName));
		if (oldUserCode != null) {
			// 防刷时间：5分钟
			Date exceptionTime = DateUtil.offset(oldUserCode.getUpdateTime(), DateField.MINUTE, 5);
			if (exceptionTime.getTime() > nowDate.getTime()) {
				return R.error("操作太频繁，请稍等再试");
			}
		}

		// 生成6位随机数
		String verifyCode = String.valueOf((int) (Math.random() * 900000 + 100000));
		SendSmsResponse sendSmsResponse = aliyunUtils.sendSms(userName, verifyCode);
		if (sendSmsResponse.getCode().equals("OK")) {
			// 把随机数存到数据库，给登录时做检验
			UserCode userCode = new UserCode();
			userCode.setCode(verifyCode);
			userCode.setPhone(userName);
			userCode.setCreateTime(nowDate);
			// 失效时间
			Date expireTime = DateUtil.offset(nowDate, DateField.MINUTE, 10);
			userCode.setExpireTime(expireTime);
			userCode.setUpdateTime(nowDate);
			if (oldUserCode != null) {
				userCode.setId(oldUserCode.getId());
				userCodeService.updateById(userCode);
			} else {
				userCodeService.save(userCode);
			}

			return R.ok();
		} else {
			return R.error("验证码发送失败");
		}
	}

	@Override
	public R login2(Map<String, Object> param) {
		Date nowDate = DateUtil.date();
		String userName = (String) param.get("userName");
		String code = (String) param.get("code");
		String mac = (String) param.get("mac");
		if (StringUtils.isBlank(mac)) {
			return R.error("mac参数不存在");
		}

		UserCode userCode = userCodeService.getOne(new QueryWrapper<UserCode>().lambda()
				.eq(UserCode::getPhone, userName)
				.eq(UserCode::getCode, code));
		if (userCode == null) {
			return R.error(501, "验证码不正确，请重新获取");
		}
		// 判断验证码是否有效
		long betweenSecond = nowDate.getTime() - userCode.getExpireTime().getTime();
		if (betweenSecond > 0) {
			return R.error(501, "验证码已失效，请重新获取");
		}

		UserEntity userEntity = userService.getOne(new QueryWrapper<UserEntity>().lambda()
				.eq(UserEntity::getUsername, userName)
				.eq(UserEntity::getType, 0));

		if (userEntity == null) {
			userEntity = new UserEntity();
			userEntity.setUsername(userName);
			userEntity.setPassword(userName);
			userEntity.setCreateBy(1);
			userEntity.setCreateTime(new Date());
		}
		// 保存token和mac
		userEntity.setMac(mac);
		userEntity.setToken(TokenGenerator.generateValue());
		userEntity.setStatus(1);
		userEntity.setLoginTime(nowDate);
		// 新增或者修改
		userService.saveOrUpdate(userEntity);
		// 构建响应参数
		AppUserDTO appUser = new AppUserDTO();
		appUser.setUserId(userEntity.getId());
		appUser.setUserName(userEntity.getUsername());
		appUser.setLoginState(userEntity.getStatus());
		appUser.setLoginTime(nowDate);
		appUser.setToken(userEntity.getToken());

		return R.ok().put("data", appUser);
	}

	@Override
	public R verifyToken2(Map<String, Object> param, HttpServletRequest request) {
		String mac = (String) param.get("mac");
		// 从请求头里获取token
		String token = request.getHeader("token");

		UserEntity userEntity = userService.getOne(new QueryWrapper<UserEntity>().lambda()
				.eq(UserEntity::getToken, token)
				.eq(UserEntity::getMac, mac)
				.eq(UserEntity::getType, 0));
		if (userEntity == null) {
			return R.error("设备token不存在");
		}

		return R.ok();
	}

	@Override
	public R smsSend(Map<String, Object> param) {
		Date nowDate = new Date();
		String userName = (String) param.get("phoneNumber");
		UserEntity userEntity = userService.getOne(new QueryWrapper<UserEntity>().lambda()
				.eq(UserEntity::getUsername, userName)
				.ne(UserEntity::getType, 1));

		if (userEntity == null) {
			return R.error("用户不存在");
		}
		// 判断账号是否过期
		if (userEntity.getPower() == 0) {
			Date usageTime = DateUtil.parse(userEntity.getUsageTime());
			if (nowDate.getTime() > usageTime.getTime()) {
				return R.error("用户已过期，请联系管理员");
			}
		}

		// 查数据是否已有该用户的验证码数据，首先判断上一次验证码是否有超过五分钟并防刷，然后判断做新增还是修改
		UserCode oldUserCode = userCodeService.getOne(new QueryWrapper<UserCode>().lambda()
				.eq(UserCode::getUserId, userEntity.getId()));
		if (oldUserCode != null) {
			// 防刷时间：5分钟
			Date exceptionTime = DateUtil.offset(oldUserCode.getUpdateTime(), DateField.MINUTE, 5);
			if (exceptionTime.getTime() > nowDate.getTime()) {
				return R.error("操作太频繁，请稍等再试");
			}
		}

		// 生成6位随机数
		String verifyCode = String.valueOf((int) (Math.random() * 900000 + 100000));
		SendSmsResponse sendSmsResponse = aliyunUtils.sendSms(userName, verifyCode);
		if (sendSmsResponse.getCode().equals("OK")) {
			// 把随机数存到数据库，给登录时做检验
			UserCode userCode = new UserCode();
			userCode.setCode(verifyCode);
			userCode.setUserId(userEntity.getId());
			userCode.setCreateTime(nowDate);
			// 失效时间
			Date expireTime = DateUtil.offset(nowDate, DateField.MINUTE, 10);
			userCode.setExpireTime(expireTime);
			userCode.setUpdateTime(nowDate);
			if (oldUserCode != null) {
				userCode.setId(oldUserCode.getId());
				userCodeService.updateById(userCode);
			} else {
				userCodeService.save(userCode);
			}

			return R.ok();
		} else {
			return R.error("验证码发送失败");
		}
	}

	@Override
	public R login(Map<String, Object> param) {
		Date nowDate = DateUtil.date();
		String userName = (String) param.get("userName");
		String code = (String) param.get("code");
		String mac = (String) param.get("mac");
		if (StringUtils.isBlank(mac)) {
			return R.error("mac参数不存在");
		}
		UserEntity userEntity = userService.getOne(new QueryWrapper<UserEntity>().lambda()
				.eq(UserEntity::getUsername, userName)
				.ne(UserEntity::getType, 1));

		if (userEntity == null) {
			return R.error("用户不存在");
		}
		// 判断账号是否过期
		if (userEntity.getPower() == 0) {
			Date usageTime = DateUtil.parse(userEntity.getUsageTime());
			if (nowDate.getTime() > usageTime.getTime()) {
				return R.error("用户已过期，请联系管理员");
			}
		}

		UserCode userCode = userCodeService.getOne(new QueryWrapper<UserCode>().lambda()
				.eq(UserCode::getUserId, userEntity.getId())
				.eq(UserCode::getCode, code));
		if (userCode == null) {
			return R.error(501, "验证码不正确，请重新获取");
		}
		// 判断验证码是否有效
		long betweenSecond = nowDate.getTime() - userCode.getExpireTime().getTime();
		if (betweenSecond > 0) {
			return R.error(501, "验证码已失效，请重新获取");
		}
		// 保存token和mac
		userEntity.setMac(mac);
		userEntity.setToken(TokenGenerator.generateValue());
		userEntity.setStatus(1);
		userEntity.setLoginTime(nowDate);
		userService.updateById(userEntity);

		AppUserDTO appUser = new AppUserDTO();
		appUser.setUserId(userEntity.getId());
		appUser.setUserName(userEntity.getUsername());
		appUser.setLoginState(userEntity.getStatus());
		appUser.setLoginTime(nowDate);
		appUser.setToken(userEntity.getToken());

		return R.ok().put("data", appUser);
	}

	@Override
	public R loginOut(Map<String, Object> param) {
		String userName = (String) param.get("userName");
		UserEntity userData = userService.getOne(new QueryWrapper<UserEntity>().lambda()
				.eq(UserEntity::getUsername, userName)
				.ne(UserEntity::getType, 1));

		if (userData == null) {
			return R.error("用户不存在");
		}

		// 生成新的token和mac
		userData.setMac("");
		userData.setToken(TokenGenerator.generateValue());
		userData.setStatus(0);
		userService.updateById(userData);
		return R.ok();
	}

	@Override
	public R verifyToken(Map<String, Object> param, HttpServletRequest request) {
		String mac = (String) param.get("mac");
		// 从请求头里获取token
		String token = request.getHeader("token");

		UserEntity userEntity = userService.getOne(new QueryWrapper<UserEntity>().lambda()
				.eq(UserEntity::getToken, token)
				.eq(UserEntity::getMac, mac)
				.ne(UserEntity::getType, 1));
		if (userEntity == null) {
			return R.error("设备token不存在");
		}
		// 判断账号是否过期
		Date nowDate = new Date();
		if (userEntity.getPower() == 0) {
			Date usageTime = DateUtil.parse(userEntity.getUsageTime());
			if (nowDate.getTime() > usageTime.getTime()) {
				return R.error("用户已过期，请联系管理员");
			}
		}

		return R.ok();
	}

	@Override
	public R getContentByGroupId(Map<String, Object> param) {
		List<ContentsVO> list = new ArrayList<>();
		Integer groupId = (Integer) param.get("groupId");
		List<Contents> contentsList = contentsService.list(new QueryWrapper<Contents>().lambda()
				.eq(groupId != null, Contents::getGroupid, groupId)
				.orderByDesc(Contents::getCreateTime));

		if (!contentsList.isEmpty()) {
			for (Contents content : contentsList) {
				// 复制出VO对象，方便设置图片信息
				ContentsVO contentsVO = BeanUtil.copyProperties(content, ContentsVO.class);
				List<ContentImages> imagesList = contentImagesService.list(new QueryWrapper<ContentImages>().lambda()
						.eq(ContentImages::getContentid, contentsVO.getId()));
				contentsVO.setContentImages(imagesList);
				list.add(contentsVO);
			}
		}
		return R.ok().put("data", list);
	}
}
